#include  "main.h"
#define Mod2sparse_block 10  // Number of entries to block together for memory allocation 

/*Structure representing a non-zero entry,
 or the header for a row or column*/
typedef struct mod2entry
{  int row, col, TempCol;        // Row and column indexes ,starting at 0, 
                                 // and with -1 for a row or column header  
   int VariableLevel,CheckLevel; // used in the serial decoding, express
                                 // the level of the variable node and check node 
  struct mod2entry *left, *right,// Pointers to entries adjacent in row and column,
                   *up, *down;   // or to headers.  Free entries are linked by 'left'. 
  double pr;					 // R, information from check point to varible point 
  double lr;					 // Q, information from varible point to check point
  double pr1;
  double lr1;
  int prq;
  int lrq;
  int srq;
  int prq1;
  int lrq1;
} mod2entry;
/* Block of entries allocated all at once */
typedef struct mod2block 
{
  struct mod2block *next;            // Next block that has been allocated 
  mod2entry entry[Mod2sparse_block]; // Entries in this block 
} mod2block;

/* Representation of a sparse matrix */
typedef struct	
{ 
  int n_rows;		      // Number of rows in the matrix 
  int n_cols;		      // Number of columns in the matrix 
  mod2entry *rows;	      // Pointer to array of row headers
  mod2entry *cols;	      // Pointer to array of column headers 
  mod2block *blocks;	  // Blocks that have been allocated 
  mod2entry *next_free;	  // Next free entry 
} mod2sparse;

/* MACROS TO GET AT ELEMENTS OF A SPARSE MATRIX.  The 'first', 'last', 'next',
   and 'prev' macros traverse the elements in a row or column.  Moving past
   the first/last element gets one to a header element, which can be identified
   using the 'at_end' macro.  Macros also exist for finding out the row 
   and column of an entry, and for finding out the dimensions of a matrix. */

#define mod2sparse_first_in_row(m,i) ((m)->rows[i].right) /* Find the first   */
#define mod2sparse_first_in_col(m,j) ((m)->cols[j].down)  /* or last entry in */
#define mod2sparse_last_in_row(m,i) ((m)->rows[i].left)   /* a row or column  */
#define mod2sparse_last_in_col(m,j) ((m)->cols[j].up)
#define mod2sparse_next_in_row(e) ((e)->right)             /* Move from one entry to     */
#define mod2sparse_next_in_col(e) ((e)->down)              /* another in any of the four */
#define mod2sparse_prev_in_row(e) ((e)->left)              /* possible directions        */
#define mod2sparse_prev_in_col(e) ((e)->up)   
#define mod2sparse_at_end(e) ((e)->row<0)                  /* See if we've reached the end*/
#define mod2sparse_row(e) ((e)->row)      /* Find out the row or column index */
#define mod2sparse_col(e) ((e)->col)      /* of an entry (indexes start at 0) */
#define mod2sparse_rows(m) ((m)->n_rows)  /* Get the number of rows or columns*/
#define mod2sparse_cols(m) ((m)->n_cols)  /* in a matrix                      */

/* POSSIBLE LU DECOMPOSITION STRATEGIES.  For use with mod2sparse_decomp. */
typedef enum 
{ Mod2sparse_first, 
  Mod2sparse_mincol, 
  Mod2sparse_minprod
} mod2sparse_strategy;

/* PROCEDURES TO MANIPULATE SPARSE MATRICES. */
void mod2sparse_mulvec(mod2sparse *, char *, char *);
mod2sparse *mod2sparse_allocate (int, int);
mod2entry *mod2sparse_insert (mod2sparse *, int, int);
void simulation();
mod2sparse *Make_LDPC(int Matrix[][H_ColNum], int StartRow, int RowNumber, int ColNumber);
mod2sparse *Make_QCLDPC(int Matrix[][NB_FAC],int nb, int mb, int z);
double degree(mod2sparse *H, double *lam, double *rou);

